package com.ttg.web.utils;

import com.ttg.common.entities.BaseResult;
import com.ttg.common.entities.RattingTask;
import com.ttg.common.enums.ErrorCodeEnums;
import com.ttg.common.enums.TaskEnum;
import com.ttg.common.enums.TaskStatusEnum;
import com.ttg.common.enums.TaskTypeEnum;
import com.ttg.common.exception.BaseException;
import com.ttg.common.utils.DateTimeUtil;
import com.ttg.common.utils.IntegerUtil;
import com.ttg.model.pojo.TaskInfo;
import com.ttg.web.dao.BankPublicPrimitiveDao;
import com.ttg.web.dao.TaskInfoDao;
import com.ttg.web.dao.VipInfoDao;
import com.ttg.web.service.TaskWarnNoticeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;

@Slf4j
@Component
@Order
@Aspect
public class TaskAspectUtil {

    @Autowired
    private TaskInfoDao taskInfoDao;

    @Autowired
    private VipInfoDao vipInfoDao;

    @Autowired
    private TaskWarnNoticeService taskWarnNoticeService;

    @Autowired
    private BankPublicPrimitiveDao bankPublicPrimitiveDao;

    @Autowired
    private PlatformTransactionManager transactionManager;


    @Around(value = "@annotation(task)")
    public Object before(ProceedingJoinPoint point, RattingTask task) throws Throwable{
        TaskEnum taskEnum = task.taskEnum();
        TaskInfo taskInfo = taskInfoDao.getByTag(taskEnum.getTaskTag());
        if (Objects.isNull(taskInfo)){
            //任务标签不存在
            throw new BaseException(ErrorCodeEnums.TASK_TAG_ABSENT.getErrcode(),ErrorCodeEnums.TASK_TAG_ABSENT.getMsg());
        }
        if (StringUtils.isNotBlank(taskInfo.getTaskPreTaskId())){
            if(taskInfo.getTaskPreTaskId().contains(",")){
                String[] preTaskIds = taskInfo.getTaskPreTaskId().split(",");
                for(String preTaskId : preTaskIds){
                    preCheck(Integer.valueOf(preTaskId));
                }
            }else {
                preCheck(Integer.valueOf(taskInfo.getTaskPreTaskId()));
            }
        }
        //重置任务状态
        taskInfoDao.setTaskInProgress(taskEnum.getTaskTag());
        return point.proceed();
    }


    @AfterThrowing(value = "@annotation(task)",throwing = "ex")
    public void afterThrow(JoinPoint point, RattingTask task,Throwable ex){
        TaskEnum taskEnum = task.taskEnum();
        //任务失败推送短信
        try {
            taskWarnNoticeService.errorReport(taskEnum.getTaskName());
        }catch (Exception e){
            log.error("短信通道异常========================>{}", LocalDateTime.now());
        }
        //修改任务状态
        taskInfoDao.setTaskFail(taskEnum.getTaskTag(),ex.getMessage());
    }


    @After(value = "@annotation(task)")
    public void after(JoinPoint point, RattingTask task){
        TaskEnum taskEnum = task.taskEnum();
        Integer excuteDate = Integer.valueOf(DateTimeUtil.formatYYYYMMDD(LocalDate.now()));
        if (TaskEnum.isIntegralTask(taskEnum)){
            afterForIntegralTasks(taskEnum,excuteDate );
            return;
        }
        taskInfoDao.updateLastExcuteDateByTag(taskEnum.getTaskTag(),excuteDate);
    };

    public void preCheck(Integer taskId){
        //检查前置任务是否成功执行
        TaskInfo preTask = taskInfoDao.getById(taskId);
        Integer excuteDate = Integer.valueOf(DateTimeUtil.formatYYYYMMDD(LocalDate.now()));
        if (!IntegerUtil.equals(preTask.getTaskStatus(),TaskStatusEnum.NORMAL.getStatus())){
            //执行任务的前置任务失败
            throw new BaseException(ErrorCodeEnums.TASK_PRE_EXECUTED_FAIL.getErrcode(),ErrorCodeEnums.TASK_PRE_EXECUTED_FAIL.getMsg() + ",task_tag:" + preTask.getTaskTag());
        }
        if (!excuteDate.equals(preTask.getTaskLastExcuteDate())){
            //执行任务的前置任务未执行
            throw new BaseException(ErrorCodeEnums.TASK_PRE_UNEXECUTED_TODAY.getErrcode(),ErrorCodeEnums.TASK_PRE_UNEXECUTED_TODAY.getMsg() + ",task_tag:" + preTask.getTaskTag());
        }
    }


    /**
     * 只对于积分任务的after
     * @param taskEnum
     */
    public void afterForIntegralTasks (TaskEnum taskEnum, Integer excuteDate){
        //事务
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        //隔离级别
        definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        //传播行为
        definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = transactionManager.getTransaction(definition);
        try {
            taskInfoDao.updateLastExcuteDateByTag(taskEnum.getTaskTag(),excuteDate);
            if (TaskEnum.isVipIntegralTask(taskEnum)){
                //个人积分任务
                Integer count = taskInfoDao.countTodayUnExcuteSameTypeTask(TaskTypeEnum.VIP_GROW_TASK.getType(),excuteDate);
                if (count == 0){
                    //统计当日积分
                    vipInfoDao.sumTodayIntegral(excuteDate);
                }
            }else {
                //商户积分任务
                Integer count = taskInfoDao.countTodayUnExcuteSameTypeTask(TaskTypeEnum.MCT_GROW_TASK.getType(),excuteDate);
                if (count == 0){
                    //统计当日积分
                    bankPublicPrimitiveDao.sumTodayIntegral(excuteDate);
                }
            }
            transactionManager.commit(status);
        }catch (Exception e){
            transactionManager.rollback(status);
            throw  e;
        }

    }


}
